package com.ericsson.webservice.dealRequest;
/**
 * 解密
 */
import java.security.MessageDigest;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class CryptoUtil
{

    private static byte[] codes = new byte[256];

    private static char[] alphabet =
            "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".toCharArray();

    static {
        for (int i = 0; i < 256; i++) {
            codes[i] = -1;
        }
        for (int i = 'A'; i <= 'Z'; i++) {
            codes[i] = (byte) (i - 'A');
        }
        for (int i = 'a'; i <= 'z'; i++) {
            codes[i] = (byte) (26 + i - 'a');
        }
        for (int i = '0'; i <= '9'; i++) {
            codes[i] = (byte) (52 + i - '0');
        }
        codes['+'] = 62;
        codes['/'] = 63;
    }

    public static byte[] base64decode(char[] data) {
        int len = ((data.length + 3) / 4) * 3;
        if (data.length > 0 && data[data.length - 1] == '=') {
            --len;
        }
        if (data.length > 1 && data[data.length - 2] == '=') {
            --len;
        }
        byte[] out = new byte[len];
        byte[] codes = new byte[256];

        for (int i = 0; i < 256; i++) {
            codes[i] = -1;
        }
        for (int i = 'A'; i <= 'Z'; i++) {
            codes[i] = (byte) (i - 'A');
        }
        for (int i = 'a'; i <= 'z'; i++) {
            codes[i] = (byte) (26 + i - 'a');
        }
        for (int i = '0'; i <= '9'; i++) {
            codes[i] = (byte) (52 + i - '0');
        }
        codes['+'] = 62;
        codes['/'] = 63;

        int shift = 0; // # of excess bits stored in accum
        int accum = 0; // excess bits
        int index = 0;
        for (int ix = 0; ix < data.length; ix++) {
            int value = codes[data[ix] & 0xFF]; // ignore high byte of char
            if (value >= 0) { // skip over non-code
                accum <<= 6; // bits shift up by 6 each time thru
                shift += 6; // loop, with new bits being put in
                accum |= value; // at the bottom.
                if (shift >= 8) { // whenever there are 8 or more shifted in,
                    shift -= 8; // write them out (from the top, leaving any
                    out[index++] = // excess at the bottom for next iteration.
                            (byte) ((accum >> shift) & 0xff);
                }
            }
        }
        if (index != out.length) {
            throw new Error("miscalculated data length!");
        }

        return out;
    }

    public static char[] base64encode(byte[] data) {
        char[] out = new char[((data.length + 2) / 3) * 4];

        for (int i = 0, index = 0; i < data.length; i += 3, index += 4) {
            boolean quad = false;
            boolean trip = false;

            int val = (0xFF & (int) data[i]);
            val <<= 8;
            if ((i + 1) < data.length) {
                val |= (0xFF & (int) data[i + 1]);
                trip = true;
            }
            val <<= 8;
            if ((i + 2) < data.length) {
                val |= (0xFF & (int) data[i + 2]);
                quad = true;
            }
            out[index + 3] = alphabet[(quad ? (val & 0x3F) : 64)];
            val >>= 6;
            out[index + 2] = alphabet[(trip ? (val & 0x3F) : 64)];
            val >>= 6;
            out[index + 1] = alphabet[val & 0x3F];
            val >>= 6;
            out[index + 0] = alphabet[val & 0x3F];
        }
        return out;
    }

    public static byte[] MD5Encode(String origin) {
        String resultString = null;
        resultString = new String(origin);
        try {
            resultString = new String(origin);
            MessageDigest md = MessageDigest.getInstance("MD5");
            return md.digest(resultString.getBytes("UTF8"));
        } catch (Exception ex) {
            throw new Error("MD5! Encode Error");
        }
    }

    public static byte[] MD5Encode(byte[] origin) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            return md.digest(origin);
        } catch (Exception ex) {
            throw new Error("MD5! Encode Error");
        }
    }

    /**
     * 鍔犲瘑绠楁硶
     * 
     * @param input
     * @param key
     * @param iv
     * @return
     */
    public static String DesEncode(byte[] input, byte[] key, byte[] iv) {
        byte[] output = new byte[] {0, 0};
        try {
            IvParameterSpec zeroIv = new IvParameterSpec(new byte[8]);
            SecretKeySpec keySpec = new SecretKeySpec(key, "DES");
            Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, keySpec, zeroIv);
            IvParameterSpec encryptionIv = new IvParameterSpec(iv, 0, 8);
            cipher.init(Cipher.ENCRYPT_MODE, keySpec, encryptionIv);
            output = cipher.doFinal(input);

        } catch (Exception e) {

            throw new RuntimeException(e);
        }
        return String.valueOf(CryptoUtil.base64encode(output));
    }

    /**
     * 瑙ｅ瘑绠楁硶
     * 
     * @param input
     * @param key
     * @param iv
     * @return
     */
    public static byte[] DesDecode(byte[] input, byte[] key, byte[] iv) {
        byte[] output = new byte[] {0, 0};
        try {
            IvParameterSpec zeroIv = new IvParameterSpec(new byte[8]);
            SecretKeySpec keySpec = new SecretKeySpec(key, "DES");
            Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, keySpec, zeroIv);
            IvParameterSpec encryptionIv = new IvParameterSpec(iv, 0, 8);
            cipher.init(Cipher.DECRYPT_MODE, keySpec, encryptionIv);
            output = cipher.doFinal(input);

        } catch (Exception e) {

            throw new RuntimeException(e);
        }
        return output;
    }

}

